package com.iotp.service.authority;

import com.iotp.dao.authority.AuthorityDAO;
import com.iotp.entity.authority.Authority;
import com.iotp.service.base.BaseServiceImpl;
import com.iotp.utils.common.DataUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;

/**
 * 系统权限业务接口实现类
 * @author Assassin
 */
@Service("authorityService")
public class AuthorityServiceImpl extends BaseServiceImpl implements AuthorityService {

	// Fields

	@Autowired
	private AuthorityDAO authorityDAO;// 系统权限DAO接口
//	@Autowired
//	private ChainDefinitionSectionService chainDefinitionSectionService;// 自定义URL权限配置业务接口
//	@Autowired
//	private CustomRealm customRealm;// 自定义Shiro Realm

	// Methods

	/**
	* 添加系统权限
	* @param orgId 标识信息-机构Id
	* @param orgCode 标识信息-机构编码
	* @param menuId 标识信息-菜单id
	* @param authorityName 基本信息-权限名称
	* @param authorityDesc 基本信息-权限说明
	* @param authorityKey 授权信息-权限标识
	* @param authorityUrl 授权信息-权限地址，多个地址使用逗号分隔
	* @return Long authorityId 添加后的数据库主键值
	*/
	@Override
	public Long addRoot(Long orgId, String orgCode, Long menuId, String authorityName, String authorityDesc, String authorityKey, String authorityUrl) {
		// 构造系统权限参数实体
		Authority authority = new Authority();
		
		// 标识信息
		authority.setAuthorityCode(DataUtil.getAuthorityCode(queryCurrentMaxAuthorityCode(orgId, 1, 0L), null, orgCode));// 添加根权限authorityLeve=1 & authorityPid=0L
		authority.setAuthorityType(1);// Set 标识信息-权限类型->默认权限类型=>1
		authority.setOrgId(orgId);// Set 标识信息-机构Id
		authority.setMenuId(menuId);// Set 标识信息-菜单id
		
		// 状态信息
		authority.setAuthoryityStatus(1);// Set 状态信息-权限数据状态->默认数据状态=>1
		authority.setIsDel(0);// Set 状态信息-是否删除[1-是 | 0-否]->默认删除状态=>0
		authority.setAuthorityOrder(null);// Set 状态信息-权限排序->默认排序=>NULL
		
		// 层级信息
		authority.setAuthorityLevel(1);// Set 层级信息-权限层级->添加根权限默认级别=>1
		authority.setIsParent(0);// Set 层级信息-是否父级[1-是 | 0-否]->新添加权限默认是否父级=>0
		authority.setAuthorityPid(0L);// Set 层级信息-父级Id[ROOT-0]->添加根权限默认父级Id=>0L
		
		// 基本信息
		authority.setAuthorityName(authorityName);// Set 基本信息-权限名称
		authority.setAuthorityDesc(authorityDesc);// Set 基本信息-权限说明
		
		// 授权信息
		authority.setAuthorityKey(authorityKey);// Set 授权信息-权限标识
		authority.setAuthorityUrl(authorityUrl);// Set 授权信息-权限地址
		
		// 时间信息
		Long createTime = System.currentTimeMillis();
		authority.setCreateTime(createTime);// Set 时间信息-创建时间
		authority.setUpdateTime(null);// Set 时间信息-更新时间[初始化=NULL]
		
		// 调用系统权限DAO接口
		this.authorityDAO.insert(authority);
		
		// 重新加载权限信息
//		relaodPermission();
		
		// 返回插入后的主键值
		return authority.getAuthorityId();
	}

   /**
	* 添加系统子权限
	* @param authorityPid 层级信息-父级权限Id
	* @param orgId 标识信息-机构Id
	* @param orgCode 标识信息-机构编码
	* @param menuId 标识信息-菜单id
	* @param authorityName 基本信息-权限名称
	* @param authorityDesc 基本信息-权限说明
	* @param authorityKey 授权信息-权限标识
	* @param authorityUrl 授权信息-权限地址，多个地址使用逗号分隔
	* @return Long authorityId 添加后的数据库主键值
	*/
	@Override
	public Long addSub(Long authorityPid, Long orgId, String orgCode, Long menuId, String authorityName,
			String authorityDesc, String authorityKey, String authorityUrl) {
		// 构造系统权限参数实体
		Authority authority = new Authority();
		// 查询父权限信息
		Authority parentAuthority = this.authorityDAO.selectById(authorityPid);
		Integer authorityLevel = parentAuthority.getAuthorityLevel() + 1;// 根据父权限Id计算当前子权限级别
		
		// 标识信息
		authority.setAuthorityCode(DataUtil.getAuthorityCode(queryCurrentMaxAuthorityCode(orgId, authorityLevel, authorityPid), parentAuthority.getAuthorityCode(), orgCode));
		authority.setAuthorityType(1);// Set 标识信息-权限类型->默认权限类型=>1
		authority.setOrgId(orgId);// Set 标识信息-机构Id
		authority.setMenuId(menuId);// Set 标识信息-菜单id
		
		// 状态信息
		authority.setAuthoryityStatus(1);// Set 状态信息-权限数据状态->默认数据状态=>1
		authority.setIsDel(0);// Set 状态信息-是否删除[1-是 | 0-否]->默认删除状态=>0
		authority.setAuthorityOrder(null);// Set 状态信息-权限排序->默认排序=>NULL
		
		// 层级信息
		authority.setAuthorityLevel(authorityLevel);// Set 层级信息-权限层级->添加子权限级别=>authorityLevel
		authority.setIsParent(0);// Set 层级信息-是否父级[1-是 | 0-否]->新添加权限默认是否父级=>0
		authority.setAuthorityPid(authorityPid);// Set 层级信息-父级Id[ROOT-0]->添加子权限父级Id=>authorityPid
		
		// 基本信息
		authority.setAuthorityName(authorityName);// Set 基本信息-权限名称
		authority.setAuthorityDesc(authorityDesc);// Set 基本信息-权限说明
		
		// 授权信息
		authority.setAuthorityKey(authorityKey);// Set 授权信息-权限标识
		authority.setAuthorityUrl(authorityUrl);// Set 授权信息-权限地址
		
		// 时间信息
		Long createTime = System.currentTimeMillis();
		authority.setCreateTime(createTime);// Set 时间信息-创建时间
		authority.setUpdateTime(null);// Set 时间信息-更新时间[初始化=NULL]
		
		// 调用系统权限DAO接口
		this.authorityDAO.insert(authority);
		
		// 子权限添加成功，更新父级权限信息
		if(parentAuthority.getIsParent().intValue() == 0) {
			editIsParent(parentAuthority.getAuthorityId(), 1);
		}
		
		// 重新加载权限信息
//		relaodPermission();
		
		// 返回插入后的主键值
		return authority.getAuthorityId();
	}
	
	
   /**
	* 删除系统权限
	* @param authorityId 主键值
	*/
	@Override
	public void delete(Long authorityId) {
		// 调用系统权限DAO接口
		this.authorityDAO.delete(authorityId);
		// 重新加载权限信息
//		relaodPermission();
	}

   /**
	* 更新系统权限
	* @param authorityId 标识信息-权限Id[主键值]
	* @param authoryityStatus 状态信息-权限数据状态
	* @param isDel 状态信息-是否删除[1-是 | 0-否]
	* @param authorityOrder 状态信息-权限排序
	* @param authorityName 基本信息-权限名称
	* @param authorityDesc 基本信息-权限说明
	* @param authorityKey 授权信息-权限标识
	* @param authorityUrl 授权信息-权限地址，多个地址使用逗号分隔
	*/
	@Override
	public void edit(Long authorityId, Integer authoryityStatus, Integer isDel, Integer authorityOrder, String authorityName, String authorityDesc, String authorityKey, String authorityUrl) {
		// 构造系统权限参数实体
		Authority authority = new Authority();
		authority.setAuthorityId(authorityId);// Set 标识信息-权限Id[主键值]
		authority.setAuthoryityStatus(authoryityStatus);// Set 状态信息-权限数据状态
		authority.setIsDel(isDel);// Set 状态信息-是否删除[1-是 | 0-否]
		authority.setAuthorityOrder(authorityOrder);// Set 状态信息-权限排序
		authority.setAuthorityName(authorityName);// Set 基本信息-权限名称
		authority.setAuthorityDesc(authorityDesc);// Set 基本信息-权限说明
		authority.setAuthorityKey(authorityKey);// Set 授权信息-权限标识
		authority.setAuthorityUrl(authorityUrl);// Set 授权信息-权限地址
		authority.setUpdateTime(System.currentTimeMillis());// Set 时间信息-更新时间[初始化=NULL]
		// 调用系统权限DAO接口
		this.authorityDAO.update(authority);
		// 重新加载权限信息
//		relaodPermission();
	}

   /**
	* 主键查询系统权限
	* @param -authority 参数实体
	* @return Authority 实体
	*/
	@Override
	public Authority queryById(Long authorityId) {
		// 调用系统权限DAO接口
		return this.authorityDAO.selectById(authorityId);
	}

   /**
	* 根据条件查询系统权限列表
	* @param authorityId 标识信息-权限Id[主键值]
	* @param authorityCode 标识信息-权限编码
	* @param authorityType 标识信息-权限类型
	* @param orgId 标识信息-机构Id
	* @param menuId 标识信息-菜单id
	* @param authoryityStatus 状态信息-权限数据状态
	* @param isDel 状态信息-是否删除[1-是 | 0-否]
	* @param authorityOrder 状态信息-权限排序
	* @param -authorityLeve 层级信息-权限层级
	* @param isParent 层级信息-是否父级
	* @param authorityPid 层级信息-父级Id
	* @param authorityName 基本信息-权限名称
	* @param authorityDesc 基本信息-权限说明
	* @param authorityKey 授权信息-权限标识
	* @param authorityUrl 授权信息-权限地址，多个地址使用逗号分隔
	* @param createTime 时间信息-创建时间
	* @param updateTime 时间信息-更新时间[初始化=NULL]
	* @return List<Authority> 实体List
	*/
	@Override
	public List<Authority> queryList(Long authorityId, String authorityCode, Integer authorityType, Long orgId, Long menuId, Integer authoryityStatus, Integer isDel, Integer authorityOrder, Integer authorityLevel, Integer isParent, Long authorityPid, String authorityName, String authorityDesc, String authorityKey, String authorityUrl, Long createTime, Long updateTime) {
		// 构造系统权限参数实体
		Authority authority = new Authority();
		authority.setAuthorityId(authorityId);// Set 标识信息-权限Id[主键值]
		authority.setAuthorityCode(authorityCode);// Set 标识信息-权限编码
		authority.setAuthorityType(authorityType);// Set 标识信息-权限类型
		authority.setOrgId(orgId);// Set 标识信息-机构Id
		authority.setMenuId(menuId);// Set 标识信息-菜单id
		authority.setAuthoryityStatus(authoryityStatus);// Set 状态信息-权限数据状态
		authority.setIsDel(isDel);// Set 状态信息-是否删除[1-是 | 0-否]
		authority.setAuthorityOrder(authorityOrder);// Set 状态信息-权限排序
		authority.setAuthorityLevel(authorityLevel);// Set 层级信息-权限层级
		authority.setIsParent(isParent);// Set 层级信息-是否父级[1-是 | 0-否]
		authority.setAuthorityPid(authorityPid);// Set 层级信息-父级Id[ROOT-0]
		authority.setAuthorityName(authorityName);// Set 基本信息-权限名称
		authority.setAuthorityDesc(authorityDesc);// Set 基本信息-权限说明
		authority.setAuthorityKey(authorityKey);// Set 授权信息-权限标识
		authority.setAuthorityUrl(authorityUrl);// Set 授权信息-权限地址
		authority.setCreateTime(createTime);// Set 时间信息-创建时间
		authority.setUpdateTime(updateTime);// Set 时间信息-更新时间[初始化=NULL]
		// 调用系统权限DAO接口
		return this.authorityDAO.selectList(authority);
	}

	/**
	 * 编辑权限状态（逻辑删除 | 恢复）
	 * @param authorityId 权限Id
	 * @param isDel 是否删除状态
	 */
	@Override
	public void editIsDel(Long authorityId, Integer isDel) {
		// 删除前加载出权限信息
		Authority authority = this.authorityDAO.selectById(authorityId);
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("authorityId", authorityId);
		paramsMap.put("isDel", isDel);
		paramsMap.put("updateTime", System.currentTimeMillis());
		this.authorityDAO.updateIsDel(paramsMap);
		// 逻辑删除
		if(isDel.intValue() == 1) {
			// 更新父级权限信息
			if(authority.getAuthorityPid() != null && authority.getAuthorityPid().longValue() != 0L) {
				List<Authority> psubList = querySubList(authority.getAuthorityPid());
				if(psubList == null || psubList.size() == 0) {
					this.editIsParent(authority.getAuthorityPid(), 0);
				}
			}
			// 更新子级权限信息->同步所有子权限删除状态
			if(authority.getIsParent().intValue() == 1) {
				HashMap<String, Object> subParamsMap = new HashMap<String, Object>();
				subParamsMap.put("authorityPid", authority.getAuthorityId());
				subParamsMap.put("isDel", isDel);
				subParamsMap.put("updateTime", System.currentTimeMillis());
				this.authorityDAO.updateIsDelByPid(subParamsMap);
			}
			// 所有子集都删除后，更新自身是否父级属性
			this.editIsParent(authorityId, 0);
		}
	}
	
	/**
	 * 根据父Id查询子权限信息
	 * @param authorityPid 父权限Id
	 * @return List<Authority>
	 */
	@Override
	public List<Authority> querySubList(Long authorityPid) {
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("authorityPid", authorityPid);
		paramsMap.put("isDel", 0);
		return this.authorityDAO.selectSubList(paramsMap);
	}
	
	/**
	 * 查询角色的权限
	 * @param roleId 角色Id
	 * @return List<Authority>
	 */
	@Override
	public List<Authority> queryAuthorityByRoleId(Long roleId) {
		return this.authorityDAO.selectAuthorityByRoleId(roleId);
	}
	
	/**
	 * 根据属性验证权限是否存在
	 * @param authorityId 权限Id
	 * @param authorityName 权限名称
	 * @param authorityUrl 权限地址
	 * @return List<Authority>
	 */
	@Override
	public List<Authority> queryIsAuthorityExist(Long authorityId, String authorityName, String authorityUrl) {
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("authorityId", authorityId);
		paramsMap.put("authorityName", authorityName);
		paramsMap.put("authorityUrl", authorityUrl);
		return this.authorityDAO.selectIsAuthorityExist(paramsMap);
	}
	
	/**
	 * 根据权限级别和父级别Id查询当前数据库权限最大编码
	 * @param orgId 机构Id
	 * @param authorityLevel 权限级别
	 * @param authorityPid 父级权限Id
	 * @return currentMaxAuthorityCode
	 */
	private String queryCurrentMaxAuthorityCode(Long orgId, Integer authorityLevel, Long authorityPid) {
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("orgId", orgId);
		paramsMap.put("authorityLevel", authorityLevel);
		paramsMap.put("authorityPid", authorityPid);
		return this.authorityDAO.selectCurrentMaxAuthorityCode(paramsMap);
	}
	
	/**
	 * 更新权限是否父级信息
	 * @param authorityId 权限Id
	 * @param isParent 是否父级
	 */
	private void editIsParent(Long authorityId, Integer isParent) {
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("authorityId", authorityId);
		paramsMap.put("isParent", isParent);
		paramsMap.put("updateTime", System.currentTimeMillis());
		this.authorityDAO.updateIsParent(paramsMap);
	}
	
	/**
	 * 重新加载权限信息到Shiro
	 */
//	private void relaodPermission() {
//		this.chainDefinitionSectionService.reloadFilterChains();
//		// 更新Ehcache缓存
//		this.customRealm.clearAllCache();
//	}
	
}